package edu.bu.cs673.superkids123.test;

import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.RollbackException;
import javax.transaction.SystemException;
import javax.transaction.Transaction;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.rules.MethodRule;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;


@SuppressWarnings("deprecation")
public class SessionFactoryRule implements MethodRule {
	 private SessionFactory sessionFactory;
	 private Transaction transaction;
	 private Session session;
	 
	 @Override
	 public Statement apply(final Statement statement, FrameworkMethod method,
	   Object test) {
	  return new Statement() {
	 
	   @Override
	   public void evaluate() throws Throwable {
	    sessionFactory = createSessionFactory();
	    createSession();
	    beginTransaction();
	    try {
	     statement.evaluate();
	    } finally {
	     shutdown();
	    }
	   }
	 
	  };
	 }
	 
	 private void shutdown() {
	  try {
	   try {
	    try {
	     transaction.rollback();
	    } catch (Exception ex) {
	     ex.printStackTrace();
	    }
	    session.close();
	   } catch (Exception ex) {
	    ex.printStackTrace();
	   }
	   sessionFactory.close();
	  } catch (Exception ex) {
	   ex.printStackTrace();
	  }
	 }
	 
	 private SessionFactory createSessionFactory() {
		 Configuration configuration = new Configuration();
	  configuration.addClass(edu.bu.cs673.superkids123.common.model.User.class)
	    .addClass(edu.bu.cs673.superkids123.common.model.Parent.class)
	    .addClass(edu.bu.cs673.superkids123.common.model.Child.class)
	  	.addClass(edu.bu.cs673.superkids123.common.model.Achievement.class)
	  	.addClass(edu.bu.cs673.superkids123.children.model.Activity.class)
	  	.addClass(edu.bu.cs673.superkids123.children.model.Answer.class)
	  	.addClass(edu.bu.cs673.superkids123.children.model.CompletedGame.class)
	  	.addClass(edu.bu.cs673.superkids123.children.model.CompletedLesson.class)
	  	.addClass(edu.bu.cs673.superkids123.children.model.Game.class)
	  	.addClass(edu.bu.cs673.superkids123.children.model.Lesson.class)
	  	.addClass(edu.bu.cs673.superkids123.children.model.Level.class)
	  	.addClass(edu.bu.cs673.superkids123.children.model.Question.class)
	  	.addClass(edu.bu.cs673.superkids123.parents.model.ActivityType.class)
	  	.addClass(edu.bu.cs673.superkids123.parents.model.Color.class)
	  	.addClass(edu.bu.cs673.superkids123.parents.model.Image.class)
	  	.addClass(edu.bu.cs673.superkids123.parents.model.Number.class)
	  	.addClass(edu.bu.cs673.superkids123.parents.model.Sound.class)
	  	.addClass(edu.bu.cs673.superkids123.parents.model.SystemTheme.class)
	  	.addClass(edu.bu.cs673.superkids123.common.model.Roles.class)
	  	;
	  
	  configuration.setProperty("hibernate.dialect","org.hibernate.dialect.H2Dialect");
	  configuration.setProperty("hibernate.connection.driver_class","org.h2.Driver");
	  configuration.setProperty("hibernate.connection.url", "jdbc:h2:mem");
	  configuration.setProperty("hibernate.hbm2ddl.auto", "create");
	  SessionFactory sessionFactory = configuration.buildSessionFactory();
	  return sessionFactory;
	 }
	 
	 public Session createSession() {
	  session = sessionFactory.openSession();
	  return session;
	 }
	 
	 public void commit() {
	  try {
		transaction.commit();
	} catch (SecurityException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (IllegalStateException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (RollbackException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (HeuristicMixedException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (HeuristicRollbackException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (SystemException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	 }
	 
	 public void beginTransaction() {
	  transaction = (Transaction) session.beginTransaction();
	 }
	 
	 public Session getSession() {
	  return session;
	 }
	}
